package com.jack.hhitseat.utils;

import java.util.Collections;
import java.util.Stack;

public class CalcUtl {
	
    private static Stack<String> postfixStack = new Stack<String>();// 后缀式栈
    private static Stack<Character> opStack = new Stack<Character>();// 运算符栈
    private static int[] operatPriority = new int[] { 0, 3, 2, 1, -1, 1, 0, 2 };// 运用运算符ASCII码-40做索引的运算符优先级
    
	private static boolean isOperator(char c) {
	        return c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')';
	}
	    
	    /**
	     * 按照给定的算术运算符做计算
	     *
	     * @param firstValue
	     * @param secondValue
	     * @param currentOp
	     * @return
	     */
	    private static String calculate(String firstValue, String secondValue, char currentOp) {
	        String result = "";
	        switch (currentOp) {
	        case '+':
	            result = (Integer.parseInt(firstValue) + Integer.parseInt(secondValue)) + "";
	            break;
	        case '-':
	            result = (Integer.parseInt(firstValue) - Integer.parseInt(secondValue)) + "";
	            break;
	        case '*':
	            result = (Integer.parseInt(firstValue) * Integer.parseInt(secondValue)) + "";
	            break;
	        case '/':
	            result = (Integer.parseInt(firstValue) / Integer.parseInt(secondValue)) + "";
	            break;
	        }
	        return result;
	    }

	    public static int calculate(String expression) {
	        Stack<String> resultStack = new Stack<String>();
	        prepare(expression);
	        Collections.reverse(postfixStack);// 将后缀式栈反转
	        String firstValue, secondValue, currentValue;// 参与计算的第一个值，第二个值和算术运算符
	        while (!postfixStack.isEmpty()) {
	            currentValue = postfixStack.pop();
	            if (!isOperator(currentValue.charAt(0))) {// 如果不是运算符则存入操作数栈中
	                currentValue = currentValue.replace("~", "-");
	                resultStack.push(currentValue);
	            } else {// 如果是运算符则从操作数栈中取两个值和该数值一起参与运算
	                secondValue = resultStack.pop();
	                firstValue = resultStack.pop();

	                // 将负数标记符改为负号
	                firstValue = firstValue.replace("~", "-");
	                secondValue = secondValue.replace("~", "-");

	                String tempResult = calculate(firstValue, secondValue, currentValue.charAt(0));
	                resultStack.push(tempResult);
	            }
	        }
	        return Integer.valueOf(resultStack.pop());
	    }
	    
	    public static boolean compare(char cur, char peek) {// 如果是peek优先级高于cur，返回true，默认都是peek优先级要低
	        boolean result = false;
	        if (operatPriority[(peek) - 40] >= operatPriority[(cur) - 40]) {
	            result = true;
	        }
	        return result;
	    }
	    
	    /**
	     * 数据准备阶段将表达式转换成为后缀式栈
	     */
	    private static void prepare(String expression) {
	        opStack.push(',');// 运算符放入栈底元素逗号，此符号优先级最低
	        char[] arr = expression.toCharArray();
	        int currentIndex = 0;// 当前字符的位置
	        int count = 0;// 上次算术运算符到本次算术运算符的字符的长度便于或者之间的数值
	        char currentOp, peekOp;// 当前操作符和栈顶操作符
	        for (int i = 0; i < arr.length; i++) {
	            currentOp = arr[i];
	            if (isOperator(currentOp)) {// 如果当前字符是运算符
	                if (count > 0) {
	                    postfixStack.push(new String(arr, currentIndex, count));// 取两个运算符之间的数字
	                }
	                peekOp = opStack.peek();
	                if (currentOp == ')') {// 遇到反括号则将运算符栈中的元素移除到后缀式栈中直到遇到左括号
	                    while (opStack.peek() != '(') {
	                        postfixStack.push(String.valueOf(opStack.pop()));
	                    }
	                    opStack.pop();
	                } else {
	                    while (currentOp != '(' && peekOp != ',' && compare(currentOp, peekOp)) {
	                        postfixStack.push(String.valueOf(opStack.pop()));
	                        peekOp = opStack.peek();
	                    }
	                    opStack.push(currentOp);
	                }
	                count = 0;
	                currentIndex = i + 1;
	            } else {
	                count++;
	            }
	        }
	        if (count > 1 || (count == 1 && !isOperator(arr[currentIndex]))) {// 最后一个字符不是括号或者其他运算符的则加入后缀式栈中
	            postfixStack.push(new String(arr, currentIndex, count));
	        }

	        while (opStack.peek() != ',') {
	            postfixStack.push(String.valueOf(opStack.pop()));// 将操作符栈中的剩余的元素添加到后缀式栈中
	        }
	    }

	    //?+55=89
		public static int calculateByEques(String code) {
			code = code.replace("?", "");
			int r = Integer.parseInt(code.split("=")[1]);
			try {
				return (r - Integer.parseInt(code.split("\\+")[0]));
			}catch (Exception e) {
				e.printStackTrace();
				return (r - Integer.parseInt(code.split("=")[0].split("\\+")[1]));
			}
		}
}
